package com.client.service;

import com.client.sm9.gm.sm3.SM3;
import com.client.sm9.gm.sm9.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

@Service
public class Sm9Service {
    @Autowired
    KeyService keyService;

    SM9Curve sm9Curve = new SM9Curve();
    SM9 sm9 = new SM9(sm9Curve);

    //转为字节数组第一个数为负的话，会在前面生成一个0，这个问题需要解决
    //签名---这里的私钥是Alice的私钥
    public Map<String, String> Sign(String msg) throws Exception {
        //签名
        ResultSignature signature = sm9.sign(keyService.getPpub_s(), keyService.getDs(), msg.getBytes());

        //输出信息
        Map<String, String> map = new HashMap<>();
        map.put("msg", msg);
        map.put("h", signature.tohString());
        map.put("s", signature.tosString());
        map.put("id", keyService.getId());
        return map;
    }

    //验签
    public boolean Verify(String id, String s_s, String s_h, String msg) throws Exception {

        //将16进制数转化为签名信息
        BigInteger bigInteger = new BigInteger(s_h + s_s, 16);
        BigInteger h = new BigInteger(s_h, 16);
        byte[] s = new BigInteger(s_s, 16).toByteArray();
        s= keyService.getbyte(s);

        //这里生成ResultSignature比较繁琐，主要是作者提供的构造方法不能正常使用，后面需进行封装一下
        ResultSignature signature = ResultSignature.fromByteArray(sm9Curve, bigInteger.toByteArray());
        signature.s.setFromBytes(s);
        signature.h = h;

        return sm9.verify(keyService.getPpub_s(), id, msg.getBytes(), signature);
    }

    //加密
    public String Encrypt(String id, String msg) throws Exception {

        int macKeyByteLen = SM3.DIGEST_SIZE;

        boolean isBaseBlockCipher = false;  //false加密明文的方法为基于KDF的序列密码,true加密明文的方法为分组密码算法
        ResultCipherText resultCipherText = sm9.encrypt(keyService.getPpub_e(), id, msg.getBytes(), isBaseBlockCipher, macKeyByteLen);

        return SM9Utils.toHexPureString(resultCipherText.toByteArray());
    }
    public byte[] Encrypt(String id, byte[] bytes) throws Exception {

        int macKeyByteLen = SM3.DIGEST_SIZE;

        boolean isBaseBlockCipher = false;  //false加密明文的方法为基于KDF的序列密码,true加密明文的方法为分组密码算法
        ResultCipherText resultCipherText = sm9.encrypt(keyService.getPpub_e(), id, bytes, isBaseBlockCipher, macKeyByteLen);

        return resultCipherText.toByteArray();
    }

    //解密
    public String Decrypt(String msg) throws Exception {

        int macKeyByteLen = SM3.DIGEST_SIZE;
        //密文
        BigInteger m = new BigInteger(msg, 16);
        ResultCipherText resultCipherText = ResultCipherText.fromByteArray(sm9Curve, m.toByteArray());

        boolean isBaseBlockCipher = false;  //false加密明文的方法为基于KDF的序列密码,true加密明文的方法为分组密码算法

        byte[] msgd = sm9.decrypt(resultCipherText, keyService.getDe(), keyService.getId(), isBaseBlockCipher, macKeyByteLen);

        return new String(msgd);

    }
    public byte[] Decrypt(byte[] bytes) throws Exception {

        int macKeyByteLen = SM3.DIGEST_SIZE;
        //密文
        ResultCipherText resultCipherText = ResultCipherText.fromByteArray(sm9Curve, bytes);

        boolean isBaseBlockCipher = false;  //false加密明文的方法为基于KDF的序列密码,true加密明文的方法为分组密码算法

        return sm9.decrypt(resultCipherText, keyService.getDe(), keyService.getId(), isBaseBlockCipher, macKeyByteLen);

    }
}

